﻿Imports DevExpress.XtraScheduler.Services
Imports DevExpress.XtraScheduler.Commands
Imports DevExpress.XtraScheduler.Native

Public Class SchedulerForm
    Implements IReloadCommand

    Public WithEvents aEditFormAppointment As AppointmentEditForm


    Public Property LabelQueryName As String
    Public Property RessourceQueryName As String

    Public Property Pl As PL.PLBase
    Public Property FormName As String
    Public Property CtrlName As String Implements IReloadCommand.CtrlName

    Public Property LastFetchedInterval As TimeInterval = New TimeInterval()
    Public Property GroupID As Guid? = Nothing
    Public Property ClassID As Guid? = Nothing
    Public Property CategID As Guid? = Nothing
    Public Property TypeID As Guid? = Nothing

    Public Event OnAfterLoad(ByVal sender As Object, ByVal e As System.EventArgs)
    Public Event OnLabelLoadMapping(ByVal sender As Object, ByVal e As System.EventArgs)
    Public Event OnRessourcelLoadMapping(ByVal sender As Object, ByVal e As System.EventArgs)
    Public Event OnAppointmentlLoadMapping(ByVal sender As Object, ByVal e As System.EventArgs)

    Public AllowCreate As Boolean
    Public AllowRead As Boolean
    Public AllowUpdate As Boolean
    Public AllowDelete As Boolean


    Protected Structure LabelColor
        Public LabelID As Guid
        Public CaptionName As String
        Public Color As Integer
    End Structure

    Protected listOfLabel As Dictionary(Of Long, LabelColor) = New Dictionary(Of Long, LabelColor)

    Protected Property appointment As Appointment
    Protected Property LabelQuery As MetaQuery
    Protected Property RessourceQuery As MetaQuery
    Protected aSqlcmd As System.Data.SqlClient.SqlCommand

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        '
        AllowCreate = True
        AllowRead = True
        AllowUpdate = True
        AllowDelete = True
        '
        'Dataset = New DataSet("SchedulerForm")
    End Sub

    Protected Overloads Sub Scheduler_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        LoadSchedule()
        SchedulerControl1.Start = Today
        SchedulerControl1.Storage = SchedulerStorage1
        DateNavigator1.SchedulerControl = SchedulerControl1
        RaiseEvent OnAfterLoad(SchedulerControl1, EventArgs.Empty)
    End Sub

    Public Overridable Function InitData() As DialogResult
        Dim aParamFrm As MqParamForm
        Dim aExecQuery As DialogResult = DialogResult.OK
        Dim aMq As MetaQuery = MetaQuery.GetMetaQueryByName(Pl.QueryName)
        Dim reader As SqlClient.SqlDataReader = Nothing
        Dim aDataRow As DataRow
        '
        SchedulerStorage1.Appointments.Clear()
        SchedulerStorage1.Appointments.DataSource = Nothing
        If Pl.Dataset.Tables.Contains(Pl.MetaDataTable.TableName) Then
            Pl.Dataset.Tables.Remove(Pl.MetaDataTable)
        End If
        Pl.Dataset.Clear()
        Pl.MetaDataTable.Clear()
        '
        If aMq.CommandTypeID = CommonExt.Base.IdRepository.METALIST_METACOMMANDTYPE_SP AndAlso aMq.MetaParams.Rows.Count > 0 Then
            aParamFrm = New MqParamForm(aMq.QueryName)
            aExecQuery = aParamFrm.ShowDialog()
            'On dit OK pour la form de Parametre
            If aExecQuery = DialogResult.OK Then
                '
                aSqlcmd = aMq.InitQueryParams
                Dim param As SqlClient.SqlParameter
                For Each row As DataRow In aMq.MetaParams.Rows
                    If aSqlcmd.Parameters.Contains(row("ColumnName").ToString) Then
                        param = aSqlcmd.Parameters(row("ColumnName").ToString)
                        If param IsNot Nothing AndAlso param.ParameterName = "@GroupId_FK" AndAlso Not IsDBNull(aParamFrm.SelectedParam(row("ColumnName").ToString)) Then
                            param.Value = aParamFrm.SelectedParam(row("ColumnName").ToString)
                            GroupID = CType(IIf(param.Value IsNot Nothing, Guid.Parse(param.Value.ToString), Nothing), Guid)
                            aDataRow = SystemBoxSDK.PL.CoreSDK.ListValues_PL.GetListValueByID(CType(GroupID, Guid))
                            If aDataRow IsNot Nothing Then
                                Me.Text = String.Format("{0} {1}", "Schedule for : ", aDataRow("Value_PRM"))
                            Else
                                Me.Text = String.Format("{0} {1}", "Schedule for : ", "All Groups")
                            End If
                        End If
                    Else
                        MessageWindow.ShowMessage(New Exception(String.Format("Scheduler execution, SQL Parameter not found: {0}", row("ColumnName"))))
                    End If
                Next
                '
                'On Passe la sqcmd qui a les paramêtre de rentré
                Pl.MetaDataTable.GetMetaCommand()
                LoadAppointmentinfo(True, DateTime.Today, DateTime.Today)
                Pl.Dataset.Tables.Add(Pl.MetaDataTable)
                '
            ElseIf aExecQuery = DialogResult.Cancel Then
                'More to come...
            End If
        End If
        Return aExecQuery
    End Function

    Public Overridable Sub ApplyMapping()
        '
        Dim labelColor As LabelColor

        Me.SchedulerControl1.BeginUpdate()
        SchedulerStorage1.Appointments.DataSource = Pl.Dataset.Tables(0).DefaultView
        '
        Me.SchedulerStorage1.Appointments.Labels.Clear()
        listOfLabel.Clear()
        '
        If OnLabelLoadMappingEvent Is Nothing Then
            If Not String.IsNullOrWhiteSpace(LabelQueryName) Then
                LabelQuery = MetaQuery.GetMetaQueryByName(LabelQueryName)
                LabelQuery.FillResultQuery()
                For Each row As DataRow In LabelQuery.ResultQuery.Rows
                    Me.SchedulerStorage1.Appointments.Labels.Add(SetColor(row("color")), row("MenuCaption").ToString, row("MenuCaption").ToString)
                    labelColor.LabelID = New Guid(row("Id").ToString)
                    labelColor.Color = CInt(row("color"))
                    labelColor.CaptionName = row("MenuCaption").ToString
                    listOfLabel.Add(CInt(row("Idint")), labelColor)
                Next
            End If
        Else
            RaiseEvent OnLabelLoadMapping(SchedulerStorage1, EventArgs.Empty)
        End If
        '
        If OnAppointmentlLoadMappingEvent Is Nothing Then
            SchedulerStorage1.Appointments.Mappings.AppointmentId = "Id"
            SchedulerStorage1.Appointments.Mappings.AllDay = "AllDayEvent"
            SchedulerStorage1.Appointments.Mappings.Description = "Body"
            SchedulerStorage1.Appointments.Mappings.Label = "Labelint"
            SchedulerStorage1.Appointments.Mappings.Subject = "Subject"
            SchedulerStorage1.Appointments.Mappings.Location = "Location"
            SchedulerStorage1.Appointments.Mappings.Start = "Start"
            SchedulerStorage1.Appointments.Mappings.End = "End"
            '
            ' Me.SchedulerStorage1.Appointments.Mappings.Status = "Status"
            ' Me.SchedulerStorage1.Appointments.Mappings.Type = "Type"
            '
            Me.SchedulerStorage1.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("CustomGroupId", "GroupId_FK"))
            Me.SchedulerStorage1.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("CustomClassId", "ClassId_FK"))
            Me.SchedulerStorage1.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("CustomCategoryId", "CategoryId_FK"))
            Me.SchedulerStorage1.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("CustomTypeId", "TypeId_FK"))
        Else
            RaiseEvent OnAppointmentlLoadMapping(SchedulerStorage1, EventArgs.Empty)
        End If

        Me.SchedulerControl1.EndUpdate()
        '
    End Sub

    Protected Overridable Function SetColor(ByVal afield As Object) As System.Drawing.Color
        If afield IsNot Nothing AndAlso Not IsDBNull(afield) Then
            If CType(afield, Decimal) = 0 Then
                Return System.Drawing.Color.FromArgb(CInt(afield))
            Else
                Return System.Drawing.Color.FromArgb(CInt(afield))
            End If
        End If
    End Function

    'Protected Sub SchedulerStorage1_AppointmentChanging(sender As Object, e As DevExpress.XtraScheduler.PersistentObjectCancelEventArgs) Handles SchedulerStorage1.AppointmentChanging
    '    Dim aAppt As Appointment = TryCast(e.Object, Appointment)
    '    Dim aDataRowView As DataRowView
    '    Dim aRow As DataRow
    '    If aAppt IsNot Nothing Then
    '        aDataRowView = TryCast(aAppt.GetRow(SchedulerStorage1), DataRowView)
    '        If aDataRowView IsNot Nothing Then
    '            aRow = aDataRowView.Row
    '            If aRow IsNot Nothing Then
    '                'aRow("LabelId_FK") = listOfLabel(CLng(aRow("Labelint")))
    '                'Pl.Save()
    '                'OutStandingIssue: A finir.
    '                'Pl.ValidateRow(aRow)
    '                'If aRow.HasErrors Then
    '                '    e.Cancel = True
    '                'End If
    '            End If
    '        End If
    '    End If
    'End Sub

    Protected Overridable Sub SchedulerStorage1_AppointmentInserting(sender As Object, e As PersistentObjectCancelEventArgs) Handles SchedulerStorage1.AppointmentInserting
        Dim aAppt As Appointment = TryCast(e.Object, Appointment)
        If aAppt IsNot Nothing Then
            SchedulerStorage1.SetAppointmentId(aAppt, Guid.NewGuid)
        End If
    End Sub

    Protected Overridable Sub SchedulerStorage1_AppointmentsInserted(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PersistentObjectsEventArgs) Handles SchedulerStorage1.AppointmentsInserted
        Dim aAppt As Appointment = TryCast(e.Objects(0), Appointment)
        Dim aRow As DataRow
        Dim aDataRowView As DataRowView
        If aAppt IsNot Nothing Then
            SchedulerControl1.BeginUpdate()
            aDataRowView = TryCast(aAppt.GetRow(SchedulerStorage1), DataRowView)
            If aDataRowView IsNot Nothing Then
                aRow = aDataRowView.Row
                If aRow IsNot Nothing Then
                    aRow("Id") = aAppt.Id
                    If aRow.Table.Columns.Contains("Labelint") AndAlso aRow.Table.Columns.Contains("LabelId_FK") Then
                        aRow("LabelId_FK") = listOfLabel(CLng(aRow("Labelint"))).LabelID
                    End If
                    Pl.Save()
                    'LastFetchedInterval = New TimeInterval()
                    'Pl.MetaDataTable.Clear()
                    'Me.SchedulerStorage1.RefreshData()
                End If
            End If
            SchedulerControl1.EndUpdate()
            RefreshScheduler()
        End If
    End Sub

    Protected Overridable Sub SchedulerStorage1_AppointmentsChanged(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PersistentObjectsEventArgs) Handles SchedulerStorage1.AppointmentsChanged
        Dim aAppt As Appointment = TryCast(e.Objects(0), Appointment)
        Dim aRow As DataRow
        Dim aDataRowView As DataRowView
        If aAppt IsNot Nothing Then
            SchedulerControl1.BeginUpdate()
            aDataRowView = TryCast(aAppt.GetRow(SchedulerStorage1), DataRowView)
            If aDataRowView IsNot Nothing Then
                aRow = aDataRowView.Row
                If aRow IsNot Nothing Then
                    If aRow.Table.Columns.Contains("Labelint") AndAlso aRow.Table.Columns.Contains("LabelId_FK") Then
                        aRow("LabelId_FK") = listOfLabel(CLng(aRow("Labelint"))).LabelID
                    End If
                    Pl.Save()
                    'LastFetchedInterval = New TimeInterval()
                    'Pl.MetaDataTable.Clear()
                    'Me.SchedulerStorage1.RefreshData()
                End If
            End If
            SchedulerControl1.EndUpdate()
            RefreshScheduler()
        End If
    End Sub

    Protected Overridable Sub SchedulerStorage1_AppointmentsDeleted(sender As Object, e As PersistentObjectsEventArgs) Handles SchedulerStorage1.AppointmentsDeleted
        Dim aAppt As Appointment = CType(e.Objects(0), Appointment)
        If aAppt IsNot Nothing Then
            SchedulerControl1.BeginUpdate()
            aAppt.Delete()
            'aDataRowView = TryCast(aAppt.GetRow(SchedulerStorage1), DataRowView)
            'If aDataRowView IsNot Nothing Then
            '    aRow = aDataRowView.Row
            '    If aRow IsNot Nothing Then
            '        aRow.Delete()
            Pl.Save()

            ' Me.SchedulerStorage1.RefreshData()
            'End If
            'End If
            SchedulerControl1.EndUpdate()
            RefreshScheduler()
        End If
    End Sub



    'http://www.devexpress.com/Support/Center/Question/Details/Q212656

    Private Sub RefreshScheduler()
        BeginInvoke(New MethodInvoker(AddressOf RefreshData))
    End Sub


    Private Sub RefreshData()
        If SchedulerControl1.Services.SchedulerState.IsDataRefreshAllowed Then
            SchedulerControl1.BeginUpdate()

            LastFetchedInterval = New TimeInterval()
            Pl.MetaDataTable.Clear()
            SchedulerStorage1.RefreshData()

            SchedulerControl1.EndUpdate()
        End If
    End Sub

    Private Sub SchedulerControl1_AppointmentViewInfoCustomizing(sender As Object, e As AppointmentViewInfoCustomizingEventArgs) Handles SchedulerControl1.AppointmentViewInfoCustomizing
        If listOfLabel.ContainsKey(e.ViewInfo.Appointment.LabelId) Then
            e.ViewInfo.Appearance.BackColor = Color.FromArgb(listOfLabel(e.ViewInfo.Appointment.LabelId).Color)
        End If
    End Sub


    Protected Overridable Sub SchedulerControl1_InitNewAppointment(sender As Object, e As AppointmentEventArgs) Handles SchedulerControl1.InitNewAppointment
        e.Appointment.CustomFields("CustomGroupId") = GroupID
        e.Appointment.CustomFields("CustomClassId") = Nothing
        e.Appointment.CustomFields("CustomCategoryId") = Nothing
        e.Appointment.CustomFields("CustomTypeId") = Nothing
    End Sub

    Public Sub ReloadCommand() Implements CommonExt.IReloadCommand.ReloadCommand
        LoadSchedule()
    End Sub

    '' Customize the popup menu. 
    Protected Overridable Sub SchedulerControl1_PopupMenuShowing(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PopupMenuShowingEventArgs) Handles SchedulerControl1.PopupMenuShowing

        Dim aCopyItem As SchedulerMenuItem
        Dim aCutItem As SchedulerMenuItem
        Dim aPasteItem As SchedulerMenuItem

        If e.Menu.Id = DevExpress.XtraScheduler.SchedulerMenuItemId.DefaultMenu Then
            Dim item As DevExpress.XtraScheduler.SchedulerMenuItem = e.Menu.GetMenuItemById(DevExpress.XtraScheduler.SchedulerMenuItemId.NewAppointment)
            If Not (item Is Nothing) Then
                ' Rename the menu item for the 'New Appointment' action. 
                item.Caption = "Open My Appointment Form"
            End If
            aPasteItem = New SchedulerMenuItem("Paste", AddressOf PasteAppt)
            aPasteItem.BeginGroup = True
            If appointment Is Nothing Then
                aPasteItem.Enabled = False
            End If
            e.Menu.Items.Add(aPasteItem)
        End If

        If e.Menu.Id = DevExpress.XtraScheduler.SchedulerMenuItemId.AppointmentMenu Then
            ' Insert a new item into the Scheduler popup menu and handle its click event.
            aCopyItem = New SchedulerMenuItem("Copy", AddressOf CopyAppt)
            aCopyItem.BeginGroup = True
            e.Menu.Items.Add(aCopyItem)
            aCutItem = New SchedulerMenuItem("Cut", AddressOf CutAppt)
            e.Menu.Items.Add(aCutItem)


            Dim labelSubMenu As SchedulerPopupMenu = e.Menu.GetPopupMenuById(SchedulerMenuItemId.LabelSubMenu)

            If listOfLabel.Count = 0 Then
                e.Menu.RemoveMenuItem(SchedulerMenuItemId.LabelSubMenu)
                Return
            End If
            Dim i As Integer = 0
            Dim menuItem As New SchedulerMenuCheckItem
            labelSubMenu.Items.Clear()
            For Each labelColor In listOfLabel
                menuItem = New SchedulerMenuCheckItem(labelColor.Value.CaptionName, Me.SchedulerControl1.SelectedAppointments(0).LabelId.Equals(i), UserInterfaceObjectHelper.CreateBitmap(New AppointmentLabel(Color.FromArgb(Convert.ToInt32(labelColor.Value.Color)), String.Empty), &H10, &H10), AddressOf OnCheckedChanged)
                menuItem.Tag = labelColor.Key
                labelSubMenu.Items.Add(menuItem)
                i += 1
            Next
        End If
    End Sub

    Private Sub OnCheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
        Me.SchedulerControl1.SelectedAppointments(0).LabelId = Convert.ToInt32((CType(sender, DXMenuItem)).Tag, System.Globalization.CultureInfo.InvariantCulture)
    End Sub

    Protected Overridable Sub CopyAppt(ByVal sender As Object, ByVal e As EventArgs)
        appointment = SchedulerControl1.SelectedAppointments(0).Copy
    End Sub

    Protected Overridable Sub CutAppt(ByVal sender As Object, ByVal e As EventArgs)
        appointment = SchedulerControl1.SelectedAppointments(0).Copy
        SchedulerControl1.SelectedAppointments(0).Delete()
    End Sub

    Protected Overridable Sub PasteAppt(ByVal sender As Object, ByVal e As EventArgs)
        Dim newAppt As Appointment
        If appointment IsNot Nothing Then
            newAppt = appointment.Copy
            SchedulerStorage1.SetAppointmentId(newAppt, Guid.NewGuid)
            newAppt.Start = SchedulerControl1.SelectedInterval.Start
            newAppt.End = SchedulerControl1.SelectedInterval.Start
            SchedulerStorage1.Appointments.Add(newAppt)
        End If
    End Sub

    Protected Overridable Sub SchedulerControl_EditAppointmentFormShowing(ByVal sender As Object, ByVal e As AppointmentFormEventArgs) Handles SchedulerControl1.EditAppointmentFormShowing
        Dim apt As Appointment = e.Appointment
        ' Required to open the recurrence form via context menu.
        'Dim openRecurrenceForm As Boolean = apt.IsRecurring AndAlso SchedulerStorage1.Appointments.IsNewAppointment(apt)
        '' Create a custom form.
        aEditFormAppointment = New AppointmentEditForm(CType(sender, SchedulerControl), apt)

        If GroupID Is Nothing Then
            aEditFormAppointment.LockGroup = False
        Else
            aEditFormAppointment.LockGroup = True
        End If

        aEditFormAppointment.Update()
        Try
            ' Required for skins support.
            aEditFormAppointment.LookAndFeel.ParentLookAndFeel = SchedulerControl1.LookAndFeel

            e.DialogResult = aEditFormAppointment.ShowDialog()
            'SchedulerControl1.Refresh()
            e.Handled = True
        Finally
            aEditFormAppointment.Dispose()
        End Try
    End Sub

    Private Sub LoadButtonItem1_ItemClick(sender As Object, e As ItemClickEventArgs) Handles LoadButtonItem1.ItemClick
        LoadSchedule()
    End Sub

    Protected Overridable Sub LoadSchedule()
        If InitData() = Windows.Forms.DialogResult.OK Then
            Me.Cursor = Cursors.WaitCursor
            ApplyMapping()
            '
            LastFetchedInterval = New TimeInterval()
            SchedulerStorage1.RefreshData()
            '
            SchedulerControl1.Visible = True
            SplitContainerControl1.Visible = True
            DateNavigator1.Visible = True
            Me.Cursor = Cursors.Default
        Else
            GroupID = Nothing
            SchedulerControl1.Visible = False
            DateNavigator1.Visible = False
            SplitContainerControl1.Visible = False
        End If
    End Sub

    Protected Overridable Sub SchedulerStorage1_FetchAppointments(sender As Object, e As FetchAppointmentsEventArgs) Handles SchedulerStorage1.FetchAppointments
        Dim aStart As DateTime = e.Interval.Start
        Dim aEnd As DateTime = e.Interval.End

        ' Check if the requested interval is outside lastFetchedInterval
        If ((aStart <= LastFetchedInterval.Start) OrElse (aEnd >= LastFetchedInterval.End)) Then
            '
            LastFetchedInterval = New TimeInterval((aStart - TimeSpan.FromDays(14)), (aEnd + TimeSpan.FromDays(14)))
            ' Load Data
            LoadAppointmentinfo(False, aStart, aEnd)
        End If
    End Sub

    Protected Overridable Sub LoadAppointmentinfo(ByVal InitEmpty As Boolean, ByVal startdate As DateTime, ByVal enddate As DateTime)
        If Pl IsNot Nothing AndAlso Pl.MetaDataTable IsNot Nothing AndAlso aSqlcmd IsNot Nothing Then
            SchedulerStorage1.BeginUpdate()
            Pl.MetaDataTable.Clear()
            'On Passe la sqcmd qui a les paramêtre de rentré
            Pl.MetaDataTable.GetMetaCommand()
            '
            aSqlcmd.Parameters("@Start").Value = startdate
            aSqlcmd.Parameters("@End").Value = enddate
            aSqlcmd.Parameters("@GroupId_FK").Value = IIf(InitEmpty, Guid.Empty, GroupID)
            '
            Pl.MetaDataTable.FillResultQuery(SqlCmd:=aSqlcmd)
            SchedulerStorage1.EndUpdate()
        End If
    End Sub
End Class
